/*******************************************************************************
 * Copyright 2011 Mile Orešković
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package com.mileoresko.hierarchism;

public class HSMTransition {

    private static final String PSEUDOCHOICE_FROM = "[Pseudochoice from ";
    private static final String ON = " on ";
    private static final String INTERNAL_IN = "[Internal in ";
    private static final String END_BRACKET = "]";
    private static final String TO = " to ";
    private static final String THROUGH = " through ";
    private static final String FROM = "[From ";
    private static final String LOG_TRANSITION_TYPE_NOT_PROPERLY_DEFINED = "[Transition type not properly defined - should never happen]";

    static final int TRANSITION_TYPE_COMMON = 1;
    static final int TRANSITION_TYPE_INTERNAL = 2;
    static final int TRANSITION_TYPE_PSEUDOCHOICE = 3;

    private final HSMBareState sourceState;
    private final HSMEvent event;
    private final HSMBareState destinationState;
    private final HSMTransitionListener transitionListener;
    private final int transitionType;
    private final boolean loggable;

    private String transitionDescription;

    HSMTransition(final HSMBareState sourceState, final HSMEvent event, final HSMBareState destinationState,
            final HSMTransitionListener transitionListener, boolean loggable) {
        this.sourceState = sourceState;
        this.event = event;
        this.destinationState = destinationState;
        this.transitionListener = transitionListener;
        this.loggable = loggable;
        if (destinationState == sourceState) {
            transitionType = TRANSITION_TYPE_INTERNAL;
        } else if (destinationState == null) {
            transitionType = TRANSITION_TYPE_PSEUDOCHOICE;
        } else {
            transitionType = TRANSITION_TYPE_COMMON;
        }
    }

    HSMBareState getDestinationState() {
        return destinationState;
    }

    HSMEvent getEvent() {
        return event;
    }

    HSMInternalTransitionAdapter getInternalTransitionAdapter() {
        if (isInternal()) {
            return (HSMInternalTransitionAdapter) transitionListener;
        } else {
            return null;
        }
    }

    HSMBareState getSourceState() {
        return sourceState;
    }

    HSMTransitionIdentifier getTransitionIdentifier() {
        return new HSMTransitionIdentifier(sourceState, event);
    }

    HSMTransitionListener getTransitionListener() {
        return transitionListener;
    }

    int getTransitionType() {
        return transitionType;
    }

    public boolean isInternal() {
        return sourceState == destinationState;
    }

    public final boolean isLoggable() {
        return loggable;
    }

    public String toString() {
        if (transitionDescription == null) {
            StringBuffer builder = new StringBuffer();
            switch (transitionType) {
            case TRANSITION_TYPE_COMMON:
                transitionDescription = builder.append(FROM).append(sourceState).append(THROUGH).append(event).append(
                        TO).append(destinationState).append(END_BRACKET).toString();
                break;
            case TRANSITION_TYPE_INTERNAL:
                transitionDescription = builder.append(INTERNAL_IN).append(sourceState).append(ON).append(event).append(
                        END_BRACKET).toString();
                break;
            case TRANSITION_TYPE_PSEUDOCHOICE:
                transitionDescription = builder.append(PSEUDOCHOICE_FROM).append(sourceState).append(ON).append(event).append(
                        END_BRACKET).toString();
                break;
            default:
                transitionDescription = LOG_TRANSITION_TYPE_NOT_PROPERLY_DEFINED;
            }
        }
        return transitionDescription;
    }
}
